package rpc.packet.codec;


import rpc.common.enumeraion.CompressType;
import rpc.common.enumeraion.PackageType;
import rpc.common.enumeraion.RpcError;
import rpc.common.enumeraion.SerializerCode;
import rpc.common.exception.RpcException;
import rpc.common.extension.ExtensionLoader;
import rpc.intf.CommonSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import lombok.extern.slf4j.Slf4j;
import rpc.intf.Compress;
import rpc.intf.impl.compressAlgorithm.GzipCompress;
import rpc.intf.impl.serializer.KryoSerializer;
import rpc.packet.RpcMessage;

import java.util.List;

/**
 * 解码器
 */
@Slf4j
public class CommonDecoder extends ReplayingDecoder {
    private static final int MAGIC_NUMBER = 0xCAFEBABE;
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
        int magic = in.readInt();
        if (magic != MAGIC_NUMBER) {
            log.debug("不识别的协议包: {}", magic);
            throw new RpcException(RpcError.UNKNOWN_PROTOCOL);
        }
        //获取包类型
        byte packageCode = in.readByte();
        //获取对应的序列化器
        byte serializerCode = in.readByte();
        //获取对应的压缩器
        byte compressCode = in.readByte();
        RpcMessage rpcMessage = RpcMessage.builder()
                .packageType(packageCode)
                .serializer(serializerCode)
                .compress(compressCode).build();

        Class<?> packageClass = PackageType.getPackageType(packageCode);

        if (packageClass == null) {
            log.debug("不识别的数据包: {}", packageCode);
            throw new RpcException(RpcError.UNKNOWN_PACKET_TYPE);
        }

        log.debug("解码的对象类型: {}", packageClass);

        //CommonSerializer serializer = CommonSerializer.getByCode(serializerCode);
        int length = in.readInt();
        byte[] bodyBytes = new byte[length];
        in.readBytes(bodyBytes);
        //利用加载器 加载一个 单列
        Compress compress = ExtensionLoader
                .getExtensionLoader(Compress.class)
                .getExtension(CompressType.getName(compressCode));
        bodyBytes = compress.decompress(bodyBytes);

        //利用加载器 加载一个 单列
        CommonSerializer commonSerializer = ExtensionLoader
                .getExtensionLoader(CommonSerializer.class)
                .getExtension(SerializerCode.getName(serializerCode));
        Object obj = commonSerializer.deserialize(bodyBytes, packageClass);
        rpcMessage.setData(obj);

        out.add(rpcMessage);
    }
}
